package com.yuju.account.service.impl;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.yuju.account.enums.AccountReturnCodeEnum;
import com.yuju.account.enums.BusinessTypeDetailEnum;
import com.yuju.account.enums.BusinessTypeEnum;
import com.yuju.account.enums.RefundAccountReturnEnum;
import com.yuju.account.model.RefundRecordModel;
import com.yuju.account.service.IAccountService;
import com.yuju.account.service.IPayService;
import com.yuju.account.service.IRefundRecordService;
import com.yuju.cache.RedisCache;
import com.yuju.common.Result;
import com.yuju.common.util.http.HttpClientHandler;
import com.yuju.common.util.http.HttpWrapper;
import com.yuju.common.util.http.IHttpClientCallBack;
import com.yuju.constant.CacheKey;
import com.yuju.constant.Constant;
import com.yuju.enums.ReturnCodeEnum;
import com.yuju.enums.ReturnStatusEnum;
import com.yuju.enums.SeqCodeEnum;
import com.yuju.enums.StatusEnum;
import com.yuju.enums.WxPayForScanReturnCodeEnum;
import com.yuju.exception.BusinessException;
import com.yuju.group.model.HotelModel;
import com.yuju.group.service.ICodeGenService;
import com.yuju.group.service.IHotelService;
import com.yuju.model.account.AccountModel;
import com.yuju.util.ConfigUtil;

/**
 * 
 * 类名：PayServiceImpl  <br />
 *
 * 功能：支付
 *
 *
 * @author : xuehj <br />
 * @Date : 2018年2月7日 上午9:28:42  <br />
 * @version : 1.1 <br />
 */
@Service
public class PayServiceImpl implements IPayService {
	private RedisCache<String, String> cache = RedisCache.getInstance();
	@Autowired
	IRefundRecordService refundRecordService;
	@Autowired
	ICodeGenService codeGenService;
	@Autowired
	IAccountService accountService;
	@Autowired
	IHotelService hotelService;
	@Override
	public Result pay(AccountModel model) {
		// 支付系统访问接口url
		String payServerUrl = ConfigUtil.get(Constant.URL_PAY_SERVER);
		Byte businessDetail = model.getBusinessTypeDetail();
		// 微信支付
		if (BusinessTypeDetailEnum.BUSINESS_TYPE_DETAIL_WX.getValue() == businessDetail) {
			// 如果该酒店未开启微信支付，则直接返回
			if (StatusEnum.FALSE.getValue() == Byte.valueOf(cache.get(model.getHotelId() + Constant.IS_ENABLE_WECHAT_PAY + CacheKey.KEY_HOT_PARAM))) {
				return null;
			}
			
			// 调起微信支付
			// 判断支付结果，执行退款逻辑
			Result result = weChatPay(model.getAccountCode(), model.getAuthCode(), 
					model.getMoney(),model.getHotelId(),model.getGroupId());// 此处为支付子系统返回的结果
//			Result result = null; // 此处为支付子系统返回的结果
			if (result.getStatus() == 1) {
				model.setVoucherNo(result.getData().toString());
				accountService.updateSelective(model);
				return result;
			} else {
				throw new BusinessException(result.getReturnCode(), result.getReturnMsg()+","+result.getData());
			}
		}
		// 支付宝支付
		else if (BusinessTypeDetailEnum.BUSINESS_TYPE_DETAIL_ZFB.getValue() == businessDetail) {
			if (StatusEnum.FALSE.getValue() == Byte.valueOf(cache.get(model.getHotelId() + Constant.IS_ENABLE_ALIPAY + CacheKey.KEY_HOT_PARAM))) {
				return null;
			}
			
			/*
			 *  *@param outTradeNo:订单号 <br/>
		     * 		    totalAmount:金额<br/>
		     * 		    authCode:付款条码<br/>
		     * 		    body:订单描述<br/>
		     *		    operatorId:操作员编号<br/>
		     *		    storeId:分店ID<br/>
			 */
			String outTradeNo = model.getAccountCode();
			String totalAmount = model.getMoney().toString();
			String authCode = model.getAuthCode();
			String body = model.getBusinessDetail();
			String operatorId = model.getCreateUserId();
			String storeId = model.getHotelId();
			
			Result result = alipay(outTradeNo, totalAmount, authCode, body, operatorId, storeId);
			if (result.getStatus() == 1) {
				model.setVoucherNo(result.getData().toString());
				return result;
			} else {
				throw new BusinessException(result.getReturnCode(), result.getReturnMsg());
			}
		}
		return null;
	}

	@Override
	public Result refund(AccountModel model) {
		// 支付系统访问接口url
		String payServerUrl = ConfigUtil.get(Constant.URL_PAY_SERVER);
		Byte businessDetail = model.getBusinessTypeDetail();
		// 微信支付
		if (BusinessTypeDetailEnum.BUSINESS_TYPE_DETAIL_WXTK.getValue() == businessDetail) {
			// 如果该酒店未开启微信支付，则直接返回
			if (StatusEnum.FALSE.getValue() == Byte.valueOf(cache.get(model.getHotelId() + Constant.IS_ENABLE_WECHAT_PAY + CacheKey.KEY_HOT_PARAM))) {
				return null;
			}
			
			// 调起微信退款
			// 判断退款结果，执行退款逻辑
			
			Result result = weChatRefund(model, model.getVoucherNo(), model.getMoney());//此处为支付子系统返回的结果
//			Result result = null; // 此处为支付子系统返回的结果
			if (result.getStatus() == 1) {
				return result;
			} else {
				throw new BusinessException(result.getReturnCode(), result.getReturnMsg()+","+result.getData());
			}
		}
		// 支付宝退款
		else if (BusinessTypeDetailEnum.BUSINESS_TYPE_DETAIL_ZFBTK.getValue() == businessDetail) {
			if (StatusEnum.FALSE.getValue() == Byte.valueOf(cache.get(model.getHotelId() + Constant.IS_ENABLE_ALIPAY + CacheKey.KEY_HOT_PARAM))) {
				return null;
			}
			
			/*
			 *       outTradeNo:订单号 <br/>
		     *		 refundAmount:金额 <br/>
		     *		 refundReason：退款原因<br/>
		     *		 storeId：门店编号
			 */
			// 调起支付宝退款
			// 判断退款结果，执行退款逻辑
			Result result = alipayRefund(model); // 此处为支付子系统返回的结果
			return result;
		}
		return null;
	}
	/**
	 * 微信刷卡支付k
	 * 功能：<br/>
	 *	@param orderNo //订单号
	 *	@param authCode //授权码
	 *	@param totalMoney //总金额
	 * @author sunyl
	 * @Date 2018年2月7日 下午4:19:49 <br/>
	 */
	private Result weChatPay(String orderNo,String authCode,BigDecimal totalMoney,String hotelId,String groupId){
		Result re = new Result();
		/*http://pay.yu500.com*/
		String url =  ConfigUtil.get(Constant.URL_PAY_SERVER);
		String[] urls = url.split("://");
		HttpWrapper httpWrapper = new HttpWrapper("post", urls[0],urls[1], null, null);
		// 设置Action
		httpWrapper.setAction("weChatPay/microPayForService");
		Map<String, Object> headers = new HashMap<String, Object>();
		headers.put("Content-Type", "application/json");
		httpWrapper.setHeaders(headers);
		/*json*/
		JSONObject param = new JSONObject();
		param.put("orderNo", orderNo);
		param.put("authCode", authCode);
		param.put("totalMoney", totalMoney);
		param.put("hotelId", hotelId);
		param.put("groupId", groupId);
		httpWrapper.setParam(param.toJSONString());
		HttpClientHandler handler = HttpClientHandler.getInstance();
		try {
			handler.execute(httpWrapper, new IHttpClientCallBack() {
				@Override
				public void execute(Object obj) {
					JSONObject json = JSON.parseObject(obj.toString());
					Result get = json.toJavaObject(Result.class);
					if(get.getStatus() == ReturnStatusEnum.SUCCESS.getCode()){
						Map<String,Object> resultData = (Map<String,Object>) get.getData();
						String transaction_id =resultData.get("transaction_id").toString();
						re.setStatus(ReturnStatusEnum.SUCCESS.getCode());
						re.setMsg(ReturnStatusEnum.SUCCESS.getDesc());
						re.setData(transaction_id);
						re.setReturnCode(WxPayForScanReturnCodeEnum.PAY_SUCCESS.getCode());
						re.setReturnMsg(WxPayForScanReturnCodeEnum.PAY_SUCCESS.getDesc());
					}else{
						re.setStatus(ReturnStatusEnum.FAILURE.getCode());
						re.setMsg(ReturnStatusEnum.FAILURE.getDesc());
						re.setReturnCode(WxPayForScanReturnCodeEnum.PAY_FAILURE.getCode());
						re.setReturnMsg(WxPayForScanReturnCodeEnum.PAY_FAILURE.getDesc());
						re.setData(get.getData());
					}
				}
			});
		} catch (IOException e) {
			e.printStackTrace();
		}
		return re;
	}
	/**
	 * 退款
	 * 功能：<br/>
	 *	@param  accountModel 丰富装数据以后为储存的model
	 *	@param  orderNo 订单号
	 *	@param  transactionId 微信的支付单号
	 *	@param  totalFee 总金额 
	 *	@param  refundFee 退款金额
	 * @author sunyl
	 * @Date 2018年2月7日 下午5:30:32 <br/>
	 */
	private Result weChatRefund(AccountModel accountModel,String transactionId,BigDecimal refundFee){
		Result re = new Result();
		/*http://pay.yu500.com*/
		String url =  ConfigUtil.get(Constant.URL_PAY_SERVER);
		String[] urls = url.split("://");
		HttpWrapper httpWrapper = new HttpWrapper("post", urls[0],urls[1], null, null);
		// 设置Action
		httpWrapper.setAction("weChatPay/refundForService");
		Map<String, Object> headers = new HashMap<String, Object>();
		headers.put("Content-Type", "application/json");
		httpWrapper.setHeaders(headers);
		/*json*/
		JSONObject param = new JSONObject();
		/*生成单号*/
		param.put("orderNo", accountModel.getAccountCode());
		String outRefundNo = codeGenService.generate(accountModel.getGroupId(), accountModel.getHotelId(),
				accountModel.getHotelCode(),SeqCodeEnum.REFUND_ORDER_CODE.getCode());
		if(outRefundNo == null){
			throw new BusinessException
			(ReturnCodeEnum.ORDER_NO_GEN_FALURE.getCode(), ReturnCodeEnum.ORDER_NO_GEN_FALURE.getDesc());
		}
		/*查询总的收款*/
		AccountModel accountModelParam = new AccountModel();
		accountModelParam.setVoucherNo(transactionId);
		accountModelParam.setBusinessType(BusinessTypeEnum.BUSINESS_TYPE_SK.getValue());//必须是收款
		AccountModel find = accountService.find(accountModelParam );
		if(find == null){
			throw new BusinessException(WxPayForScanReturnCodeEnum.REFUND_FAILURE.getCode(),
					WxPayForScanReturnCodeEnum.REFUND_FAILURE.getDesc()+","+AccountReturnCodeEnum.ACCOUNT_QUERY_FAILURE.getDesc());
		}
		param.put("outRefundNo", outRefundNo);
		param.put("orderNo", find.getAccountCode());
		param.put("transactionId", transactionId);
		param.put("totalFee", find.getMoney());
		param.put("refundFee", refundFee);
		param.put("hotelId", accountModel.getHotelId());
		param.put("groupId", accountModel.getGroupId());
		httpWrapper.setParam(param.toJSONString());
		HttpClientHandler handler = HttpClientHandler.getInstance();
		try {
			handler.execute(httpWrapper, new IHttpClientCallBack() {
				@Override
				public void execute(Object obj) {
					JSONObject json = JSON.parseObject(obj.toString());
					Result get = json.toJavaObject(Result.class);
					if(get.getStatus() == ReturnStatusEnum.SUCCESS.getCode()){
						re.setStatus(ReturnStatusEnum.SUCCESS.getCode());
						re.setMsg(ReturnStatusEnum.SUCCESS.getDesc());
						re.setReturnCode(WxPayForScanReturnCodeEnum.REFUND_SUCCESS.getCode());
						re.setReturnMsg(WxPayForScanReturnCodeEnum.REFUND_SUCCESS.getDesc());
						/*退款记录数据库*/
						RefundRecordModel model = new RefundRecordModel();
						model.setRefundNo(outRefundNo);
						model.setAccountId(accountModel.getId());
						model.setAccountCode(accountModel.getAccountCode());
						model.setMoney(refundFee);
						model.setHotelId(accountModel.getHotelId());
						model.setGroupId(accountModel.getGroupId());
						model.setCreateUserId(accountModel.getCreateUserId());
						model.setUpdateUserId(accountModel.getUpdateUserId());
						if(0 == refundRecordService.save(model)){
							throw new BusinessException(RefundAccountReturnEnum.REFUNDACCOUNT_SAVE_SUCCESS.getCode()
									,RefundAccountReturnEnum.REFUNDACCOUNT_SAVE_SUCCESS.getDesc());
						}
					}else{
						re.setStatus(ReturnStatusEnum.FAILURE.getCode());
						re.setMsg(ReturnStatusEnum.FAILURE.getDesc());
						re.setReturnCode(WxPayForScanReturnCodeEnum.REFUND_FAILURE.getCode());
						re.setReturnMsg(WxPayForScanReturnCodeEnum.REFUND_FAILURE.getDesc());
						re.setData(get.getData());
					}
				}
			});
		} catch (IOException e) {
			e.printStackTrace();
		}
		return re;
	}

	/**
	 * 
	 * 功能：支付宝付款<br/>
	 *@param outTradeNo:订单号 <br/>
     * 		  hotelName:门店名字 <br/>
     * 		  totalAmount:金额<br/>
     * 		  authCode:付款条码<br/>
     * 		  body:订单描述<br/>
     *		  operatorId:操作员编号<br/>
     *		  storeId:分店ID<br/>
	 * @author zhousc
	 * @Date 2018年2月8日 上午11:26:47 <br/>
	 */
	private Result alipay(String outTradeNo ,String totalAmount ,String authCode ,
			String body ,String operatorId ,String storeId){
		Result returnResult = new Result();
		// 调起支付宝支付
		/*http://pay.yu500.com*/
		String[] urls = ConfigUtil.get(Constant.URL_PAY_SERVER).split("://");
		HttpWrapper httpWrapper = new HttpWrapper("post", urls[0],urls[1], null, null);
		// 设置Action
		httpWrapper.setAction("alipay/pay");
		Map<String, Object> headers = new HashMap<String, Object>();
		headers.put("Content-Type", "application/json");
		httpWrapper.setHeaders(headers);
		//获取分店名
		HotelModel findById = hotelService.findById(storeId);
		/*json*/
		JSONObject obj = new JSONObject();
		obj.put("outTradeNo", outTradeNo);
		obj.put("hotelName", findById.getName());
		obj.put("totalAmount", totalAmount);
		obj.put("authCode", authCode);
		obj.put("body", body);
		obj.put("operatorId", operatorId);
		obj.put("storeId", storeId);
		
		httpWrapper.setParam(obj.toJSONString());
		HttpClientHandler handler = HttpClientHandler.getInstance();
		try {
			handler.execute(httpWrapper, new IHttpClientCallBack() {
			  @Override
			  public void execute(Object obj) {

				if("".equals(obj) && null == obj){
					returnResult.setStatus(ReturnStatusEnum.FAILURE.getCode());
					returnResult.setMsg(ReturnStatusEnum.FAILURE.getDesc());
				}
				JSONObject jsonObject = JSONObject.parseObject((String) obj);
				Result get = jsonObject.toJavaObject(Result.class);
				if(get.getStatus() == ReturnStatusEnum.SUCCESS.getCode()){
					returnResult.setStatus(ReturnStatusEnum.SUCCESS.getCode());
					returnResult.setMsg(ReturnStatusEnum.SUCCESS.getDesc());
					returnResult.setData(get.getData());
					returnResult.setReturnCode(get.getReturnCode());
					returnResult.setReturnMsg(get.getReturnMsg());
				}else{
					returnResult.setStatus(ReturnStatusEnum.FAILURE.getCode());
					returnResult.setMsg(ReturnStatusEnum.FAILURE.getDesc());
					returnResult.setReturnCode(get.getReturnCode());
					returnResult.setReturnMsg(get.getReturnMsg());
				}
			  }
			});
		} catch (IOException e) {
			e.printStackTrace();
		}
		return returnResult;
	}
	
	/**
	 * 
	 * 功能：支付宝退款<br/>
	 *@param outTradeNo:订单号 <br/>
     *		 refundAmount:金额 <br/>
     *		 refundReason：退款原因<br/>
     *		 storeId：门店编号
	 * @author zhousc
	 * @Date 2018年2月8日 上午11:56:16 <br/>
	 */
	private Result alipayRefund(AccountModel accountModel){
		Result returnResult = new Result();
		// 调起支付宝支付
		/*http://pay.yu500.com*/
		String[] urls = ConfigUtil.get(Constant.URL_PAY_SERVER).split("://");
		HttpWrapper httpWrapper = new HttpWrapper("post", urls[0],urls[1], null, null);
		// 设置Action
		httpWrapper.setAction("alipay/refund");
		Map<String, Object> headers = new HashMap<String, Object>();
		headers.put("Content-Type", "application/json");
		httpWrapper.setHeaders(headers);
		/*json*/
		JSONObject obj = new JSONObject();
		obj.put("outTradeNo", accountModel.getAccountCode());
		obj.put("refundAmount", accountModel.getMoney());
		obj.put("refundReason", accountModel.getBusinessDetail());
		obj.put("storeId", accountModel.getHotelId());
		
		httpWrapper.setParam(obj.toJSONString());
		HttpClientHandler handler = HttpClientHandler.getInstance();
		try {
			handler.execute(httpWrapper, new IHttpClientCallBack() {
				@Override
				public void execute(Object obj) {
					if("".equals(obj) && null == obj){
						returnResult.setStatus(ReturnStatusEnum.FAILURE.getCode());
						returnResult.setMsg(ReturnStatusEnum.FAILURE.getDesc());
					}
					JSONObject jsonObject = JSONObject.parseObject((String) obj);
					Result get = jsonObject.toJavaObject(Result.class);
					if(get.getStatus() == ReturnStatusEnum.SUCCESS.getCode()){
						returnResult.setStatus(ReturnStatusEnum.SUCCESS.getCode());
						returnResult.setMsg(ReturnStatusEnum.SUCCESS.getDesc());
						returnResult.setData(get.getData());
						returnResult.setReturnCode(get.getReturnCode());
						returnResult.setReturnMsg(get.getReturnMsg());
						//保存退款信息
						RefundRecordModel model = new RefundRecordModel();
						model.setRefundNo(get.getData().toString());
						model.setAccountId(accountModel.getId());
						model.setAccountCode(accountModel.getAccountCode());
						model.setMoney(accountModel.getMoney());
						model.setHotelId(accountModel.getHotelId());
						model.setGroupId(accountModel.getGroupId());
						model.setCreateUserId(accountModel.getCreateUserId());
						model.setUpdateUserId(accountModel.getUpdateUserId());
						if(0 == refundRecordService.save(model)){
							throw new BusinessException(RefundAccountReturnEnum.REFUNDACCOUNT_SAVE_SUCCESS.getCode()
									,RefundAccountReturnEnum.REFUNDACCOUNT_SAVE_SUCCESS.getDesc());
						}
					}else{
						returnResult.setStatus(ReturnStatusEnum.FAILURE.getCode());
						returnResult.setMsg(ReturnStatusEnum.FAILURE.getDesc());
						returnResult.setReturnCode(get.getReturnCode());
						returnResult.setReturnMsg(get.getReturnMsg());
					}
				}
			});
		} catch (IOException e) {
			e.printStackTrace();
		}
		return returnResult;
	}
}
